<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>迭代</title>
		<style>
			p{
				height: 100px;
				background-color: red;
				width: 100px;
			}
		</style>
	</head>
	<body>
		<h1>迭代器</h1>
		<p></p>
		<p></p>
		<p></p>
		<p></p>
		<p></p>


		<script>
			let aP = document.querySelectorAll('p')
			for (let s of aP) {
				s.addEventListener('click',()=>{
					console.log(6666);
				})
			}
			
		</script>

		<!-- 
		一.循环的几种方式 
		1.for循环
		用途：循环代码块一定的次数
		遍历 数组、对象(需先转换成数组)、字符串
		可以使用return、break等来中断循环
		使用 break 语句来跳出循环，使用continue 语句来跳过点前的迭代，并执行下一个迭代。
		2.for in循环
			for-in 不仅仅遍历 array 自身的属性，其还遍历 array 原型链上的所有可枚举的属性。
			for-in 并不适合用来遍历 Array 中的元素，其更适合遍历对象中的属性，这也是其被创造出来的初衷。
			却有一种情况例外，就是稀疏数组 [1,empt,5,empt]。普通for次数太多
			注:每次迭代操作会同时搜索实例或者原型属性， for-in 循环的每次迭代都会产生更多开销，
			因此要比其他循环类型慢，一般速度为其他类型循环的 1/7。
			
			缺点 :它不仅遍历数组中的元素，还会遍历自定义的属性，甚至原型链上的属性都被访问到。而且，遍历数组元素的顺序可能是随机的。
			
		3. forEach循环 
			需要注意的是，forEach 遍历的范围在第一次调用 callback 前就会确定。调用forEach 后添加到数组中
			的项不会被 callback 访问到。如果已经存在的值被改变，则传递给 callback 的值是 forEach 遍历
			到他们那一刻的值。已删除的项不会被遍历到。
			缺点: 注意：forEach循环里面没办法用break跳出循环
		
		4.for of循环
			①那 for-of 到底可以干什么呢？
			跟 forEach 相比，可以正确响应 break, continue, return。
			for-of 循环不仅支持数组，还支持大多数类数组对象，例如 DOM nodelist 对象。
			for-of 循环也支持字符串遍历，它将字符串视为一系列 Unicode 字符来进行遍历。
			for-of 也支持 Map 和 Set （两者均为 ES6 中新增的类型）对象遍历。
			
			②总结一下，for-of 循环有以下几个特征：
			这是最简洁、最直接的遍历数组元素的语法。
			这个方法避开了 for-in 循环的所有缺陷。
			与 forEach 不同的是，它可以正确响应 break、continue 和 return 语句。
			其不仅可以遍历数组，还可以遍历类数组对象和其他可迭代对象(Iterator)。
			但需要注意的是，for-of循环不支持普通对象，但如果你想迭代一个对象的属性，你可以用 for-in 循环（这也是它的本职工作）。
			
			
			最后要说的是，ES6 引进的另一个方式也能实现遍历数组的值，那就是 Iterator。
		 
		 迭代  从一个数据集合中 按照一定的顺序,去取出数据 不断的去取数据的过程
		 			这个过程我们称作迭代
				①创建迭代器 (能够创建迭代器的 就是可迭代对象)
				let iter = arr[Symbol.iterator]()
				value表示在值  done 表示迭代结束了没有
				console.log(iter.next()); {value:??,done:false}
				
				②创建一个可迭代对象 
				obj[Symbol.iterator] = function(){
					let keys = Object.keys(this)
					let num = 0;
					console.log(keys)
					return {
						next:()=>{
							let value = this[keys[num]]
							let done = num>=keys.length
							num++
							return {value,done};
						}
					}
				}
			
			
			异步的解决方案有哪些  callback   async await   promise Generator
			
			生成器 Generator
			生成器是ES6新增的一种可以对函数控制的方案，能灵活的控制函数的暂停执行，继续执行等。
			
			定义: 普通函数function定义，生成器函数function*，要在后面加*
			生成器函数可以通过 yield 来控制函数的执行
			生成器函数返回一个生成器(generator)，生成器是一个特殊的迭代器
			
			//创建一个生成器函数
			//yield 关键字
			function* createArrIterator() {
				console.log(1);
				yield* 1
				console.log(2);
			}
			//yield 与 return的区别
			
			//yield* 后续可以跟一个  iterator 接口
			function* createArrIterator(bears) {
			  yield* bears
			}
			//	返回一个遍历器对象 可以调用next
			const generator = createArrIterator(bears)
			
			generator.next()
				
			next方法带参数
			yield表达式本身没有返回值，或者说总是返回undefined。next方法可以带一个参数，该参数就会被当作上一个yield表达式的返回值。
			从语义上讲，第一个next方法用来启动遍历器对象，所以不用带有参数。
			
			
			代码
			// function playGame(hp=100){
			// 	const next = (fire)=>{
			// 		let value = hp-=fire
			// 		let done = value<=0
			// 		return {
			// 			value,
			// 			done
			// 		}
			// 	}
			// 	return  {
			// 		next
			// 	}
			// }
			// function* playGame(hp=100){
			
			// }
			
			function* playGame(hp=100){
				while(true){
					let res = yield hp
					hp-=res
					if(hp<=0){
						break
					}
				}
			}
			
		 -->
	</body>
</html>